// kate: space-indent on; indent-width 8;
.pc =$0801 "Basic Upstart Program"
:BasicUpstart($0810)

//---------------------------------------------------------
//---------------------------------------------------------
//			(Game of) Life
//---------------------------------------------------------
//---------------------------------------------------------

// Missing:
// - Random initialisation of cells
// - Generation/Population counters display
// - Sound?
// - Interface


.var Screen1 = $0400
.var Screen2 = $2000


.const WIDTH  = 40
.const HEIGHT = 25
.const LWIDTH  = 15
.const LHEIGHT = 15

//calc  can do 13x13 in one frame
//calc2 can do 15x15 in one frame


.const PRA  =  $dc00            // CIA#1 (Port Register A)
.const DDRA =  $dc02            // CIA#1 (Data Direction Register A)
.const PRB  =  $dc01            // CIA#1 (Port Register B)
.const DDRB =  $dc03            // CIA#1 (Data Direction Register B)

.var SHOWRASTERTIME = true

.pc = $0810 "Main Program"
        jsr Init
        jsr Setup
        
mloop:  .if (SHOWRASTERTIME) {
rloop:  lda $d012
        bne rloop
        lda #2
        sta $d020
        }
        jsr Calc2
        .if (SHOWRASTERTIME) {
        lda #0
        sta $d020
        }
        jsr CheckKeyboard       // will set the Z flag when 'S' key is pressed
        bne mloop
        lda saved018
        sta $d018
        rts

active: .byte $00,$04
sc1:    .byte 0
sc2:    .byte 0
scindex: .byte 0
Init:
{
        
        lda #0
        sta $d020
        sta $d021
        sta active
        lda #4
        sta active+1
        

        lda #0
        jsr clr400
        ldy #0
copy:   lda $400,y
        sta $2000,y
        lda $500,y
        sta $2100,y
        lda $600,y
        sta $2200,y
        lda $700,y
        sta $2300,y
        dey
        bne copy

        sei
        lda $1
        //and #254
        pha
        and #%11111011
        sta $1
        
        //copy the character set from ROM to RAM
        ldx #0
!loop:
        .for(var i=0; i<8; i++) {
                lda $d000+i*$100,x
                sta $3000+i*$100,x
        }
        inx
        bne !loop-
        //lda $1
        //ora #4
        //sta $1
        pla
        sta $1
        cli
        lda $d018
        and #$f0
        ora #12
        sta $d018
        
        
        ldy #7
        lda #%10000000
l2:     sta $3000,y
        dey
        bpl l2
        lda #$ff
        sta $3000
        


        lda $d018
        sta saved018
        and #$f
        sta sc1
        sta sc2
        lda sc1
        ora #%00010000  //screen at $0400
        sta sc1
        lda sc2
        ora #%10000000  //screen at $2000
        sta sc2
        lda #0
        sta scindex
        

        rts
}

saved018: .byte 0

clr400:
{
        ldx #0
loop:
        .for(var i=0; i<4; i++) {
                
                //sta $0400+i*$100,x
                sta $2000+i*$100,x
        }
        inx
        bne loop
}
Setup: 
{
        // here we should use some rand() to initialise the population
        rts
}


// Taken from http://www.c64-wiki.com/index.php/Keyboard
CheckKeyboard: 
{
        sei             // interrupts deactivated
        lda #%11111111  // CIA#1 port A = outputs 
        sta DDRA             
        lda #%00000000  // CIA#1 port B = inputs
        sta DDRB             
        lda #%11111101  // testing column 1 (COL1) of the matrix
        sta PRA
            
loop:   lda PRB
        and #%00100000  // masking row 5 (ROW5) 
        //bne loop        // wait until key "S" 

        cli             // interrupts activated

        rts             // back to BASIC
}

Calc:
{
// 00000100 thats the $04
// 00100000 thats the $20
// 00100100 and thats what we need to EOR with $04 to get $20

        // active matrix (read from) to $FA
        lda active
        sta $fa
        sta $fc
        lda active+1
        sta $fb
        // to display matrix (write to) to $FC
        eor #%00100100
        sta active+1
        sta $fd

        lda #LHEIGHT-2
        sta $ff
loopy:  lda #LWIDTH-2
        sta $fe

loopx:  ldy #0
        ldx #0
        lda ($fa),y
        beq znw
        inx     
znw:    iny
        lda ($fa),y
        beq zn
        inx
zn:     iny
        lda ($fa),y
        beq zne
        inx
zne:    ldy #WIDTH
        lda ($fa),y
        beq zw
        inx
zw:     iny
        iny
        lda ($fa),y
        beq ze
        inx
ze:     ldy #WIDTH+WIDTH
        lda ($fa),y
        beq zsw
        inx
zsw:    iny
        lda ($fa),y
        beq zs
        inx
zs:     iny
        lda ($fa),y
        beq zse
        inx
zse:    ldy #WIDTH+1
        cpx #2
        beq n2
        cpx #3
        beq n3
        lda #0
        sta ($fc),y
        
next:   inc $fa
        bne sk1
        inc $fb
sk1:    inc $fc
        bne sk2
        inc $fd
sk2:    dec $fe
        bne loopx
        lda #LWIDTH-2
        sta $fe
        
        clc
        lda $fa
        adc #WIDTH-LWIDTH+2
        sta $fa
        bcc noc
        inc $fb
noc:    clc
        lda $fc
        adc #WIDTH-LWIDTH+2
        sta $fc
        bcc noc2
        inc $fd
noc2:


        dec $ff
        bne loopy

        
        lda scindex
        eor #1
        sta scindex
        ldy scindex
        lda sc1,y
        sta $d018
        
        rts

n2:     //if the number of neighbours is 2 then (and only then) we need to determine the active cell 
        lda ($fa),y     //whatever it is (0-dead or <>0-alive), it will remain so
        sta ($fc),y
        jmp next

n3:     lda #160
        sta ($fc),y
        bne next
        
}


//This is way faster then Calc, but needs the ON cells to have a value of 1 ('A') to work
//both calc2 and calc need OFF cells to have the value of 0 ('@')
Calc2:
{
// 00000100 thats the $04
// 00100000 thats the $20
// 00100100 and thats what we need to EOR with $04 to get $20

        // active matrix (read from) to $FA
        lda active
        sta $fa
        sta $fc
        lda active+1
        sta $fb
        // to display matrix (write to) to $FC
        eor #%00100100
        sta active+1
        sta $fd

        lda #LHEIGHT-2
        sta $ff
loopy:  ldx #LWIDTH-2

loopx:  ldy #0
        clc
        tya
        adc ($fa),y
        iny
        adc ($fa),y
        iny
        adc ($fa),y
        ldy #WIDTH
        adc ($fa),y
        iny
        iny
        adc ($fa),y
        ldy #WIDTH+WIDTH
        adc ($fa),y
        iny
        adc ($fa),y
        iny
        adc ($fa),y
        ldy #WIDTH+1
        cmp #2
        beq n2
        cmp #3
        beq n3
        lda #0
        sta ($fc),y
        
next:   inc $fa
        bne sk1
        inc $fb
sk1:    inc $fc
        bne sk2
        inc $fd
sk2:    dex
        bne loopx
        lda #LWIDTH-2
        sta $fe
        
        clc
        lda $fa
        adc #WIDTH-LWIDTH+2
        sta $fa
        bcc noc
        inc $fb
noc:    clc
        lda $fc
        adc #WIDTH-LWIDTH+2
        sta $fc
        bcc noc2
        inc $fd
noc2:


        dec $ff
        bne loopy

        
        lda scindex
        eor #1
        sta scindex
        ldy scindex
        lda sc1,y
        sta $d018
        
        rts

n2:     //if the number of neighbours is 2 then (and only then) we need to determine the active cell 
        lda ($fa),y     //whatever it is (0-dead or <>0-alive), it will remain so
        sta ($fc),y
        jmp next

n3:     lda #1
        sta ($fc),y
        bne next
        
}